/******************************************************************************
 * * contact_search.c - implementation of contact search functions
 *
 * *(C) Copyright 2019 Asr International Ltd.
 * * All Rights Reserved
 * ******************************************************************************/
#include "contact_global.h"

#define CONTACTS_SEARCH_BTN_TXT_NULL     (" \n ")

/**
 * Action if pressing contact button on Contacts_Search interface
 * param (in) lv_obj_t *Btn,lv_event_t event
 * return  void
 */
void Contacts_Search_Btn_Contact_Cb(lv_obj_t *Btn,lv_event_t event)
{
    if(LV_EVENT_CLICKED != event)
    {
        return;
    }

    Contacts_Info_t *ContactInfo = g_ContactsMng.ContactsSearch.FocusContact->ContactInfo;
    lv_ll_t         *ContactsList;
    Contacts_List_t *Contact;

    ContactsList = Contacts_Get_Contacts_Operation_List(NULL);
    Contact      = _lv_ll_get_head(ContactsList);
    while (NULL != Contact)
    {
        if (ContactInfo == Contact->ContactInfo)
        {
            g_ContactsMng.InterfaceCtrl.FocusContact = Contact;
            Contacts_Update_Contacts_Interface();
            break;
        }
        Contact = _lv_ll_get_next(ContactsList, Contact);
    }

    Contacts_Create_Contacts_Details(ContactInfo, TRUE);
}

/**
 * Clear text on contact button
 * param (in) Btn: UI_Button_Desc_t *
 * return  VOID
 */
VOID Contacts_Clear_Btn_Text(UI_Button_Desc_t *Btn)
{
    lv_obj_t *Label;
    lv_obj_t *Image;
    UINT8    Len = CONTACTS_MAX_NAME_LENGTH + CONTACTS_MAX_NUMBER_LENGTH + 1;

    Btn->Valid = FALSE;
    if (0 != strcmp(Btn->BtnTxt, CONTACTS_SEARCH_BTN_TXT_NULL))
    {
        snprintf(Btn->BtnTxt, Len, CONTACTS_SEARCH_BTN_TXT_NULL);
    }

    Image = lv_obj_get_child(Btn->Button, NULL);
    Label = lv_obj_get_child(Btn->Button, Image);
    lv_label_set_text(Label, "");
    lv_obj_set_hidden(Image, true);
}

/**
 * Text changed with input method on Contacts_Search interface
 * param (in) Len: UINT8
 * return  VOID
 */
VOID Contacts_Search_Text_Changed(UINT8 Len)
{
    UI_Button_Container_Ta_Desc_t *Interface =
        &(((UI_Normal_Contact_Search_Button_Desc_t *)g_ContactsMng.InterfaceCtrl.Ctrl)->
              ButtonContainerTa);
    lv_ll_t          *ContactsList;
    UINT16           Count;
    Contacts_List_t  *Contact;
    Contacts_List_t  *ContactSearch;
    UI_Button_Desc_t *ContBtn[UI_MAX_SEARCH_CONT_BTN_NUM];
    lv_obj_t         *Label;
    lv_obj_t         *Image;
    lv_obj_t         *Cont;
    const INT8       *TaTxt;
    lv_obj_t         *Ta;
    UINT8            NewTxtLen;
    UINT8            i;
    UINT8            NameLen;
    lv_coord_t       ScrlH;

    if (ACT_ID_CONTACTS_SEARCH != g_ContactsMng.InterfaceCtrl.InterfaceId)
    {
        UI_Log_Out(UI_SUB_MODULE_FRAMEWORK, UI_LOG_LEVEL_TRACE_3, "Error! Contacts_Search_Text_Changed, interface id %d\n", g_ContactsMng.InterfaceCtrl.InterfaceId);
        return;
    }

    for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
    {
        ContBtn[i] = &Interface->ContButtonScrl.ContButton[i];
    }
    Cont       = Interface->ContButtonScrl.ContScrl.Container;
    Ta         = Interface->ContLabelTa.ContTa.TextArea;
    TaTxt      = lv_textarea_get_text(Ta);
    NewTxtLen  = strlen(TaTxt);

    ContactsList = Contacts_Get_Contacts_Operation_List(&Count);

    if (0 != Interface->ContButtonScrl.Index)
    {
        Interface->ContButtonScrl.Index = 0;
        Interface->ContButtonScrl.PosY  = 0;

        lv_list_focus_btn(Interface->ContButtonScrl.List, ContBtn[0]->Button);
    }

    g_ContactsMng.ContactsSearch.ContactsCount = 0;
    Contact                                    = _lv_ll_get_head(ContactsList);

    Interface->ContButtonScrl.PosY = 0;

    if (0 == NewTxtLen)
    {
        _lv_ll_clear(&g_ContactsMng.ContactsSearch.SearchList);
        g_ContactsMng.ContactsSearch.FocusContact = Contact;
        for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
        {
            if (Contact)
            {
                Contacts_Update_ContBtn_Des(Contact->ContactInfo, ContBtn[i]);
                Contact = _lv_ll_get_next(ContactsList, Contact);
            }
            else
            {
                Contacts_Clear_Btn_Text(ContBtn[i]);
            }
        }
    }
    else
    {
        /* upgrade contacts with NewTaTxt */
        ContactSearch = _lv_ll_get_head(&g_ContactsMng.ContactsSearch.SearchList);
        while (NULL != Contact)
        {
            NameLen = strlen(Contact->ContactInfo->Name);
            if (NewTxtLen <= NameLen)
            {
                for (i = 0; i <= (NameLen - NewTxtLen); i++)
                {
                    if (0 == strncmp(TaTxt, &(Contact->ContactInfo->Name[i]), NewTxtLen))
                    {
                        if (NULL == ContactSearch)
                        {
                            ContactSearch =
                                _lv_ll_ins_tail(&g_ContactsMng.ContactsSearch.SearchList);
                        }
                        ContactSearch->ContactInfo = Contact->ContactInfo;
                        g_ContactsMng.ContactsSearch.ContactsCount++;

                        ContactSearch = _lv_ll_get_next(&g_ContactsMng.ContactsSearch.SearchList, ContactSearch);

                        break;
                    }
                }
            }

            Contact = _lv_ll_get_next(ContactsList, Contact);
        }

        while (NULL != ContactSearch)
        {
            Contact =
                _lv_ll_get_next(&g_ContactsMng.ContactsSearch.SearchList, ContactSearch);
            _lv_ll_remove(&g_ContactsMng.ContactsSearch.SearchList, ContactSearch);
            Hal_Mem_Free(ContactSearch);
            ContactSearch = Contact;
        }

        if (0 == g_ContactsMng.ContactsSearch.ContactsCount)
        {
            if (0 < Count)
            {
                g_ContactsMng.ContactsSearch.FocusContact = NULL;
                /* set the text of the first button to empty */
                snprintf(ContBtn[0]->BtnTxt, Len, CONTACTS_SEARCH_BTN_TXT_NULL);
                Image              = lv_obj_get_child(ContBtn[0]->Button, NULL);
                Label              = lv_obj_get_child(ContBtn[0]->Button, Image);
                ContBtn[0]->TxtId  = PHONE_TEXT_ID_NOMATCHES;
                lv_label_set_text(Label, lv_lang_get_text(PHONE_TEXT_ID_NOMATCHES));
                lv_obj_set_hidden(Image, true);

                for (i = 1;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
                {
                    Contacts_Clear_Btn_Text(ContBtn[i]);
                }
            }
            Count = 0;
        }
        else
        {
            ContactSearch = _lv_ll_get_head(&g_ContactsMng.ContactsSearch.SearchList);
            g_ContactsMng.ContactsSearch.FocusContact = ContactSearch;

            for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
            {
                if (ContactSearch)
                {
                    Contacts_Update_ContBtn_Des(ContactSearch->ContactInfo, ContBtn[i]);
                    ContactSearch = _lv_ll_get_next(&g_ContactsMng.ContactsSearch.SearchList, ContactSearch);
                }
                else
                {
                    Contacts_Clear_Btn_Text(ContBtn[i]);
                }
            }

            Count = g_ContactsMng.ContactsSearch.ContactsCount;
        }
    }
    if (0 < Count)
    {
        ScrlH = Count * Interface->ContButtonScrl.Height;
        Contacts_Set_ScrlBar_Size_For_BtnCont(Cont,
                                              Interface->ContButtonScrl.List,
                                              ScrlH);
        Contacts_Set_ScrlBar_Pos_For_BtnCont(Cont,
                                             Interface->ContButtonScrl.List,
                                             ScrlH,
                                             0);
    }
    else
    {
        lv_obj_set_width(Cont, 0);
    }
} /* Contacts_Search_Text_Changed */

/**
 * Callback function for handling key pressed on Contacts_Search interface
 * param (in) Obj: lv_obj_t *
 * param (in) Key_Sta: UI_KEY_STATUS
 * param (in) Key_Val: UI_KEY_VALUE
 * return  UINT8
 */
UINT8 Contacts_Search_Key_Cb(lv_obj_t *Obj, UI_KEY_STATUS Key_Sta, UI_KEY_VALUE Key_Val)
{
    UINT8                         Ret        = 1;
    UI_Button_Container_Ta_Desc_t *Interface =
        &(((UI_Normal_Contact_Search_Button_Desc_t *)g_ContactsMng.InterfaceCtrl.Ctrl)->
              ButtonContainerTa);
    Contacts_List_t  *Contact;
    Contacts_List_t  *ContactTemp;
    lv_obj_t         *Cont;
    lv_obj_t         *Ta;
    const INT8       *TaTxt;
    INT8             Char = 0;
    lv_ll_t          *ContactsList;
    UINT16           Count;
    UINT8            TxtLen;
    UINT8            NewTxtLen;
    INT8             *Name;
    INT8             *Number;
    INT16            i;

    Cont   = Interface->ContButtonScrl.ContScrl.Container;
    Ta     = Interface->ContLabelTa.ContTa.TextArea;
    TaTxt  = lv_textarea_get_text(Ta);
    TxtLen = strlen(TaTxt);

    ContactsList = Contacts_Get_Contacts_Operation_List(&Count);

    if (KEY_RELEASED == Key_Sta)
    {
        switch (Key_Val)
        {
        case KEY_SOFTRIGHT: // clear character
        case KEY_0:
        case KEY_1:
        case KEY_2:
        case KEY_3:
        case KEY_4:
        case KEY_5:
        case KEY_6:
        case KEY_7:
        case KEY_8:
        case KEY_9:
        case KEY_ASTERISK:
            if (KEY_SOFTRIGHT == Key_Val)
            {
                lv_textarea_del_char(Ta);
            }
            else
            {
                if (KEY_ASTERISK == Key_Val)
                {
                    Char = '*';
                }
                else
                {
                    Char = Key_Val - KEY_0 + '0';
                }
                lv_textarea_add_char(Ta, Char);
            }
            TaTxt = lv_textarea_get_text(Ta);
            NewTxtLen = strlen(TaTxt);
            if (TxtLen != NewTxtLen) // text in TA changed
            {
                Contacts_Search_Text_Changed(0);
            }
            break;

        case KEY_HASH:
            /* select input method, and update TA Label */
            break;

        case KEY_UP:
            if (0 != TxtLen)
            {
                Count        = g_ContactsMng.ContactsSearch.ContactsCount;
                ContactsList = &g_ContactsMng.ContactsSearch.SearchList;
            }

            if (2 > Count)
            {   /* found contact empty or only one */
                break;
            }

            if (0 == Interface->ContButtonScrl.Index) // focus on the first button
            {
                if (UI_MAX_SEARCH_CONT_BTN_NUM >= Count)
                {
                    Interface->ContButtonScrl.Index           = Count - 1;
                    g_ContactsMng.ContactsSearch.FocusContact = _lv_ll_get_tail(ContactsList);
                    if (UI_MAX_SEARCH_CONT_BTN_NUM > Count)
                    {
                        lv_list_focus_btn(Interface->ContButtonScrl.List,
                                          Interface->ContButtonScrl.ContButton[Interface->ContButtonScrl.Index].Button);
                        Ret = 1;
                    }
                    else
                    {
                        Ret = 0;
                    }
                }
                else // number of found contacts exceeds number of buttons
                {
                    Contact     = g_ContactsMng.ContactsSearch.FocusContact;
                    ContactTemp = _lv_ll_get_prev(ContactsList, Contact);

                    if (NULL != ContactTemp)
                    {
                        /* only change button text to the previous contact, not move focus */
                        Contacts_Update_ContBtn_Des(ContactTemp->ContactInfo, &Interface->ContButtonScrl.ContButton[0]);
                        Contacts_Update_ContBtn_Des(Contact->ContactInfo, &Interface->ContButtonScrl.ContButton[1]);
                        g_ContactsMng.ContactsSearch.FocusContact = ContactTemp;
                        for (i = 2;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
                        {
                            Contact = _lv_ll_get_next(ContactsList, Contact);
                            Contacts_Update_ContBtn_Des(Contact->ContactInfo, &Interface->ContButtonScrl.ContButton[i]);
                        }

                        Interface->ContButtonScrl.PosY -= Interface->ContButtonScrl.Height;
                    }
                    else // focus at the head of contact list
                    {
                        /* jump to the tail */
                        Contact = _lv_ll_get_tail(ContactsList);
                        Contacts_Update_ContBtn_Des(Contact->ContactInfo,
                                                    &Interface->ContButtonScrl.ContButton[UI_MAX_SEARCH_CONT_BTN_NUM - 1]);
                        g_ContactsMng.ContactsSearch.FocusContact = Contact;
                        for (i = UI_MAX_SEARCH_CONT_BTN_NUM - 2;i >= 0;i--)
                        {
                            Contact = _lv_ll_get_prev(ContactsList, Contact);
                            Contacts_Update_ContBtn_Des(Contact->ContactInfo, &Interface->ContButtonScrl.ContButton[i]);
                        }

                        Interface->ContButtonScrl.Index = UI_MAX_SEARCH_CONT_BTN_NUM - 1;
                        Interface->ContButtonScrl.PosY  = Interface->ContButtonScrl.Height * (Count - UI_MAX_SEARCH_CONT_BTN_NUM);

                        Ret = 0;
                    }
                }
            }
            else
            {
                Interface->ContButtonScrl.Index--;
                g_ContactsMng.ContactsSearch.FocusContact = _lv_ll_get_prev(ContactsList, g_ContactsMng.ContactsSearch.FocusContact);

                Ret = 0; // call the default key function to move focus
            }

            Contacts_Set_ScrlBar_Pos_For_BtnCont(Cont,
                                                 Interface->ContButtonScrl.List,
                                                 Count * Interface->ContButtonScrl.Height,
                                                 - Interface->ContButtonScrl.PosY);
            break;

        case KEY_DOWN:
            if (0 != TxtLen)
            {
                Count        = g_ContactsMng.ContactsSearch.ContactsCount;
                ContactsList = &g_ContactsMng.ContactsSearch.SearchList;
            }
            printf("%s: key down, count %d\n", __FUNCTION__, Count);
            if (2 > Count)
            {   /* Contact empty or only one contact, not move focus */
                break;
            }

            if (UI_MAX_SEARCH_CONT_BTN_NUM >= Count)
            {
                Ret = 0;
                if ((Count - 1) == Interface->ContButtonScrl.Index)
                {
                    Interface->ContButtonScrl.Index           = 0;
                    g_ContactsMng.ContactsSearch.FocusContact = _lv_ll_get_head(ContactsList);
                    if (UI_MAX_SEARCH_CONT_BTN_NUM > Count)
                    {
                        lv_list_focus_btn(Interface->ContButtonScrl.List,
                                          Interface->ContButtonScrl.ContButton[0].Button);
                        Ret = 1;
                    }
                }
                else
                {
                    Interface->ContButtonScrl.Index++;
                    g_ContactsMng.ContactsSearch.FocusContact
                        = _lv_ll_get_next(ContactsList, g_ContactsMng.ContactsSearch.FocusContact);
                }
            }
            else
            {
                if ((UI_MAX_SEARCH_CONT_BTN_NUM - 1) == Interface->ContButtonScrl.Index) // focus on the last button
                {
                    Contact     = g_ContactsMng.ContactsSearch.FocusContact;
                    ContactTemp = _lv_ll_get_next(ContactsList, Contact);
                    if (NULL == ContactTemp) // at the tail of contact list
                    {
                        /* jump to the head of contact list */
                        Contact = _lv_ll_get_head(ContactsList);
                        Contacts_Update_ContBtn_Des(Contact->ContactInfo, &Interface->ContButtonScrl.ContButton[0]);
                        g_ContactsMng.ContactsSearch.FocusContact = Contact;
                        for (i = 1;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
                        {
                            Contact = _lv_ll_get_next(ContactsList, Contact);
                            Contacts_Update_ContBtn_Des(Contact->ContactInfo, &Interface->ContButtonScrl.ContButton[i]);
                        }

                        Interface->ContButtonScrl.Index = 0;
                        Interface->ContButtonScrl.PosY  = 0;

                        Ret = 0;
                    }
                    else
                    {
                        /* only change button text to the next contact, not move focus */
                        Contacts_Update_ContBtn_Des(ContactTemp->ContactInfo,
                                                    &Interface->ContButtonScrl.ContButton[UI_MAX_SEARCH_CONT_BTN_NUM - 1]);
                        Contacts_Update_ContBtn_Des(Contact->ContactInfo,
                                                    &Interface->ContButtonScrl.ContButton[UI_MAX_SEARCH_CONT_BTN_NUM - 2]);
                        g_ContactsMng.ContactsSearch.FocusContact = ContactTemp;
                        for (i = UI_MAX_SEARCH_CONT_BTN_NUM - 3;i >= 0;i--)
                        {
                            Contact = _lv_ll_get_prev(ContactsList, Contact);
                            Contacts_Update_ContBtn_Des(Contact->ContactInfo, &Interface->ContButtonScrl.ContButton[i]);
                        }

                        Interface->ContButtonScrl.PosY += Interface->ContButtonScrl.Height;
                    }
                }
                else
                {
                    Interface->ContButtonScrl.Index++;
                    g_ContactsMng.ContactsSearch.FocusContact
                        = _lv_ll_get_next(ContactsList, g_ContactsMng.ContactsSearch.FocusContact);

                    Ret = 0; // call the default key function
                }
            }

            Contacts_Set_ScrlBar_Pos_For_BtnCont(Cont,
                                                 Interface->ContButtonScrl.List,
                                                 Count * Interface->ContButtonScrl.Height,
                                                 - Interface->ContButtonScrl.PosY);
            break;

        case KEY_LEFT:
            lv_textarea_cursor_left(Ta);
            break;

        case KEY_RIGHT:
            lv_textarea_cursor_right(Ta);
            break;

        case KEY_OK:
            if (0 != TxtLen)
            {
                Count = g_ContactsMng.ContactsSearch.ContactsCount;
            }
            if (0 < Count)
            {
                Ret = 0; // call the default key function
            }
            break;

        case KEY_SOFTLEFT:
            Nav_Back(ACT_ID_ANY);
            break;

        case KEY_END:
            Nav_Home(ACT_ID_ANY);
            break;

        case KEY_DIAL:
            if (NULL != g_ContactsMng.ContactsSearch.FocusContact)
            {
                Contact = g_ContactsMng.ContactsSearch.FocusContact;
                printf("%s:dial,count %d, name %s, number %s\n",
                       __FUNCTION__, g_ContactsMng.ContactsSearch.ContactsCount,
                       Contact->ContactInfo->Name, Contact->ContactInfo->Number);
                TxtLen  = strlen(Contact->ContactInfo->Number);
                if (0 == TxtLen)
                {
                    Contacts_Create_No_Phone_Number();
                    return(Ret);
                }
                TxtLen++;
                Number = (INT8 *)Hal_Mem_Alloc(TxtLen);
                Hal_Mem_Copy(Number, Contact->ContactInfo->Number, TxtLen);
                TxtLen = strlen(Contact->ContactInfo->Name) + 1;
                Name   = (INT8 *)Hal_Mem_Alloc(TxtLen);
                Hal_Mem_Copy(Name, Contact->ContactInfo->Name, TxtLen);
                Contacts_Call_Req(Name, Number);
                return(Ret);
            }
            break;

        default:
            break;
        } /* switch */
    }

    return(Ret);
} /* Contacts_Key_Cb */

/**
 * Callback function for additional actions after Creating Contacts_Search interface
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Search_OnCreate(VOID *Ctrl)
{
    UI_Normal_Contact_Search_Button_Desc_t *Interface =
        (UI_Normal_Contact_Search_Button_Desc_t *)Ctrl;
    UI_Container_Button_Scroll_Desc_t      *ContBtnScrl =
        &Interface->ButtonContainerTa.ContButtonScrl;
    lv_obj_t                               *Image;
    lv_obj_t                               *Ta =
        Interface->ButtonContainerTa.ContLabelTa.ContTa.TextArea;
    UINT8                                  i;
    UINT16                                 ContactsCount;
    lv_coord_t                             ScrlH;
    lv_obj_t                               *Cont = ContBtnScrl->ContScrl.Container;

    for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
    {
        if (FALSE == ContBtnScrl->ContButton[i].Valid)
        {
            Image = lv_obj_get_child(ContBtnScrl->ContButton[i].Button, NULL);
            lv_obj_set_hidden(Image, true);
        }
    }

    lv_textarea_set_max_length(Ta, (CONTACTS_MAX_NAME_LENGTH - 1));

    Ime_Set_GetCharLen_Func(Contacts_Search_Text_Changed);

    Contacts_Get_Contacts_Operation_List(&ContactsCount);
    if (0 < ContactsCount)
    {
        ScrlH = ContactsCount * ContBtnScrl->Height;
        Contacts_Set_ScrlBar_Size_For_BtnCont(Cont, ContBtnScrl->List, ScrlH);
        Contacts_Set_ScrlBar_Pos_For_BtnCont(Cont, ContBtnScrl->List, ScrlH, ContBtnScrl->PosY);
    }
    else
    {
        lv_obj_set_width(Cont, 0);
    }
}

/**
 * Callback function for restoring state on Contacts_Search interface after backward from another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Search_OnRestoreState(VOID *Ctrl)
{
    UI_Normal_Contact_Search_Button_Desc_t *Interface =
        (UI_Normal_Contact_Search_Button_Desc_t *)Ctrl;
    UI_Container_Button_Scroll_Desc_t      *ContBtnScrl =
        &Interface->ButtonContainerTa.ContButtonScrl;
    lv_obj_t                               *Image;
    lv_obj_t                               *Ta =
        Interface->ButtonContainerTa.ContLabelTa.ContTa.TextArea;
    UINT8                                  i;
    UINT16                                 ContactsCount;
    lv_coord_t                             ScrlH;
    lv_obj_t *                             Cont = ContBtnScrl->ContScrl.Container;

    g_ContactsMng.InterfaceCtrl.Ctrl        = Ctrl;
    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_SEARCH;

    if (PHONE_TEXT_ID_NOMATCHES == ContBtnScrl->ContButton[0].TxtId)
    {
        for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
        {
            Image = lv_obj_get_child(ContBtnScrl->ContButton[i].Button, NULL);
            lv_obj_set_hidden(Image, true);
        }
        lv_obj_set_width(Cont, 0);
    }
    else
    {        
        if (0 < g_ContactsMng.ContactsSearch.ContactsCount)
        {
            ScrlH = ContBtnScrl->Height * g_ContactsMng.ContactsSearch.ContactsCount;
        }
        else
        {
            Contacts_Get_Contacts_Operation_List(&ContactsCount);
            ScrlH = ContBtnScrl->Height * ContactsCount;
        }
        Contacts_Set_ScrlBar_Size_For_BtnCont(Cont, ContBtnScrl->List, ScrlH);
        Contacts_Set_ScrlBar_Pos_For_BtnCont(Cont, ContBtnScrl->List, ScrlH, ContBtnScrl->PosY);
        for (i = 1;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
        {
            if (0 == strcmp(ContBtnScrl->ContButton[i].BtnTxt, CONTACTS_SEARCH_BTN_TXT_NULL))
            {
                Image = lv_obj_get_child(ContBtnScrl->ContButton[i].Button, NULL);
                lv_obj_set_hidden(Image, true);
            }
        }
    }

    lv_textarea_set_max_length(Ta, (CONTACTS_MAX_NAME_LENGTH - 1));
    Ime_Set_Mode(Interface->ButtonBar.ButtonL.ButtonIndex);
    Ime_Set_GetCharLen_Func(Contacts_Search_Text_Changed);
}

/**
 * Callback function for saving state on Contacts_Search interface before forward to another activity
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Search_OnSaveState(VOID *Ctrl)
{
    UI_Normal_Contact_Search_Button_Desc_t *Interface =
        (UI_Normal_Contact_Search_Button_Desc_t *)Ctrl;
    UI_Text_Area_Desc_t                    *ContTa =
        &(Interface->ButtonContainerTa.ContLabelTa.ContTa);
    const INT8                             *Text;
    UINT8                                  Len;

    if (0 != strlen(ContTa->TaTxt))
    {
        Hal_Mem_Free(ContTa->TaTxt);
        ContTa->TaTxt = NULL;
    }

    Text = lv_textarea_get_text(ContTa->TextArea);
    if (0 != strlen(Text))
    {
        Len           = strlen(Text) + 1;
        ContTa->TaTxt = (INT8 *)Hal_Mem_Alloc(Len);
        Hal_Mem_Copy(ContTa->TaTxt, (INT8 *)Text, Len);
    }
    else
    {
        ContTa->TaTxt = "";
    }

    Interface->ButtonBar.ButtonL.ButtonIndex = Ime_Get_Mode();
}

/**
 * Callback function for destroying Contacts_Search interface which will be popped from stack
 * param (in) Ctrl: VOID *
 * return  VOID
 */
VOID Contacts_Search_OnDestroy(VOID *Ctrl)
{
    UI_Normal_Contact_Search_Button_Desc_t *Interface =
        (UI_Normal_Contact_Search_Button_Desc_t *)Ctrl;
    UI_Container_Button_Scroll_Desc_t      *ContBtnScrl =
        &Interface->ButtonContainerTa.ContButtonScrl;
    UI_Container_Label_Ta_Desc_t           *ContLabelTa = &Interface->ButtonContainerTa.ContLabelTa;
    UINT8                                  i;

    for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
    {
        Hal_Mem_Free(ContBtnScrl->ContButton[i].BtnTxt);
    }
    if (NULL != ContLabelTa->ContTa.TaTxt)
    {
        if (0 != strlen(ContLabelTa->ContTa.TaTxt))
        {
            Hal_Mem_Free(ContLabelTa->ContTa.TaTxt);
        }
    }
    Hal_Mem_Free(Ctrl);

    g_ContactsMng.ContactsSearch.ContactsCount = 0;
    _lv_ll_clear(&g_ContactsMng.ContactsSearch.SearchList);
    g_ContactsMng.ContactsSearch.FocusContact = NULL;
}

/**
 * Create Contacts_Search interface
 * param (in) VOID
 * return  VOID
 */
VOID Contacts_Create_Contacts_Search(VOID)
{
    UI_Normal_Contact_Search_Button_Desc_t *Interface;
    UI_Container_Button_Scroll_Desc_t      *ContBtnScrl;
    UI_Container_Label_Ta_Desc_t           *ContLabelTa;
    Nav_Func_List_t                        FuncList;
    UINT8                                  Len = CONTACTS_MAX_NAME_LENGTH +
                                                 CONTACTS_MAX_NUMBER_LENGTH + 1;
    lv_ll_t                                *ContactsList;
    Contacts_List_t                        *Contact;
    UINT16                                 Count;
    UINT8                                  i;

    Interface =
        (UI_Normal_Contact_Search_Button_Desc_t *)Hal_Mem_Alloc(sizeof(
                                                                    UI_Normal_Contact_Search_Button_Desc_t));
    Hal_Mem_Set(Interface, 0, sizeof(UI_Normal_Contact_Search_Button_Desc_t));

    g_ContactsMng.InterfaceCtrl.InterfaceId = ACT_ID_CONTACTS_SEARCH;
    g_ContactsMng.InterfaceCtrl.Ctrl        = (VOID *)Interface;

    Interface->TitleBar.TxtId      = PHONE_TEXT_ID_SEARCH;
    Interface->TitleBar.TxtAlign   = LV_LABEL_ALIGN_CENTER;
    Interface->TitleBar.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    ContactsList = Contacts_Get_Contacts_Operation_List(&Count);

    if (0 == Count)
    {
        /* error */
        return;
    }

    ContBtnScrl = &Interface->ButtonContainerTa.ContButtonScrl;

    Contact = _lv_ll_get_head(ContactsList);
    g_ContactsMng.ContactsSearch.FocusContact = Contact;
    for (i = 0;i < UI_MAX_SEARCH_CONT_BTN_NUM;i++)
    {
        ContBtnScrl->ContButton[i].TxtId  = LV_LANG_TXT_ID_NONE;
        ContBtnScrl->ContButton[i].BtnTxt = (INT8 *)Hal_Mem_Alloc(Len);
        if (Contact)
        {
            ContBtnScrl->ContButton[i].Valid       = TRUE;
            ContBtnScrl->ContButton[i].ButtonIndex = i;
            ContBtnScrl->ContButton[i].ReleaseFun  = Contacts_Search_Btn_Contact_Cb;
            ContBtnScrl->ContButton[i].SymbolId2   = Contacts_Get_Contact_Memory_Symbol(Contact->ContactInfo->MemoryAndIndex);
            snprintf(ContBtnScrl->ContButton[i].BtnTxt, Len, "%s\n%s",
                     Contact->ContactInfo->Name, Contact->ContactInfo->Number);
            ContBtnScrl->ContButton[i].ReleaseFun  = Contacts_Search_Btn_Contact_Cb;

            Contact = _lv_ll_get_next(ContactsList, Contact);
        }
        else
        {
            ContBtnScrl->ContButton[i].Valid  = FALSE;
            snprintf(ContBtnScrl->ContButton[i].BtnTxt, Len, CONTACTS_SEARCH_BTN_TXT_NULL);
            ContBtnScrl->ContButton[i].SymbolId2 = "";
        }
    }

    //ContBtnScrl->Height = FP_SEARCH_LIST_H / Count;
    ContBtnScrl->Height = (UINT16)FP_SEARCH_LIST_H / UI_MAX_SEARCH_CONT_BTN_NUM;

    /* input method in Label, for example ABC/abc */
    ContLabelTa                       = &Interface->ButtonContainerTa.ContLabelTa;
    ContLabelTa->ContLabel.TxtId      = LV_LANG_TXT_ID_NONE;
    ContLabelTa->ContLabel.TxtAlign   = LV_LABEL_ALIGN_LEFT;
    ContLabelTa->ContLabel.LabelAlign = LV_ALIGN_IN_TOP_LEFT;

    ContLabelTa->ContTa.TaAlign      = LV_ALIGN_IN_BOTTOM_LEFT;
    ContLabelTa->ContTa.TaCursorHide = FALSE;
    ContLabelTa->ContTa.TaTxt        = "";

    Interface->ButtonBar.ButtonL.Valid = TRUE;
    Interface->ButtonBar.ButtonL.TxtId = PHONE_TEXT_ID_BACK;

    Interface->ButtonBar.ButtonM.Valid = TRUE;
    Interface->ButtonBar.ButtonM.TxtId = PHONE_TEXT_ID_OK;

    Interface->ButtonBar.ButtonR.Valid = TRUE;
    Interface->ButtonBar.ButtonR.TxtId = PHONE_TEXT_ID_CLEAR;

    Interface->KeyFunc = Contacts_Search_Key_Cb;

    Hal_Mem_Set(&FuncList, 0, sizeof(Nav_Func_List_t));
    FuncList.OnShow         = UI_Normal_Contact_Search_Button_Create;
    FuncList.OnCreate       = Contacts_Search_OnCreate;
    FuncList.OnRestoreState = Contacts_Search_OnRestoreState;
    FuncList.OnSaveState    = Contacts_Search_OnSaveState;
    FuncList.OnDestroy      = Contacts_Search_OnDestroy;

    Nav_Forward(ACT_ID_ANY, ACT_ID_CONTACTS_SEARCH, &FuncList, g_ContactsMng.InterfaceCtrl.Ctrl);
} /* Contacts_Create_Contacts_Search */
